/*
 * Created on Feb 15, 2005
 * Created by dfhuynh
 */
package it.okkam.longwell.ui.command;

import it.okkam.longwell.ui.command.ChangeModelCommand;
import it.okkam.longwell.ui.command.SelectGraphsCommand;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;


import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.impl.PropertyImpl;
import com.hp.hpl.jena.tdb.TDBFactory;
import com.hp.hpl.jena.vocabulary.RDF;

import edu.mit.simile.longwell.LongwellServer;
import edu.mit.simile.longwell.LongwellServlet;
import edu.mit.simile.longwell.Profile;

import edu.mit.simile.longwell.query.IAnswer;
import edu.mit.simile.longwell.query.IQueryModel;
import edu.mit.simile.longwell.query.Query;
import edu.mit.simile.longwell.query.QueryException;
import edu.mit.simile.longwell.schema.IStructuredProperty;
import edu.mit.simile.longwell.schema.IStructuredSchema;
import edu.mit.simile.longwell.tag.ITagModel;
import edu.mit.simile.longwell.ui.FlairMessage;
import edu.mit.simile.longwell.ui.FlairURL;
import edu.mit.simile.longwell.ui.InjectionManager;
import edu.mit.simile.longwell.ui.command.CommandBase;


/**
 * @author dfhuynh
 */
public class BrowseDefaultModelCommand extends CommandBase {
	final static private Logger s_logger = Logger.getLogger(BrowseDefaultModelCommand.class);
	/**
	 * @param injectionManager
	 */
	public BrowseDefaultModelCommand(InjectionManager injectionManager) {
		super(injectionManager);
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.flair.IFlairCommand#execute(edu.mit.simile.flair.FlairMessage)
	 */
	public void execute(FlairMessage msg) throws ServletException {
		try {
			VelocityContext vcContext = createContext(msg);
			HttpSession session = msg.m_request.getSession();
			String sessionId = msg.m_request.getSession().getId();
			vcContext.put("sessionId", msg.m_request.getSession().getId());
			Set schemas = getSchemas(msg);
			
			Iterator iter= schemas.iterator();
			while (iter.hasNext()){
				IStructuredSchema o = (IStructuredSchema) iter.next();
				String schema = o.getURI();
				if(schema.contains("http://www.w3.org/2002"))
					msg.m_query.addRestriction("edu.mit.simile.longwell.query.project.SchemaBasedProjector", "",  "edu.mit.simile.longwell.query.bucket.DistinctValueBucketer", "r"+schema);
			}
			IAnswer answer = performQuery(msg, vcContext);
			fillContextWithAnswer(msg, vcContext, answer);
			msg.m_ve.mergeTemplate(
				"templates/commands/browse-default-model.vt",
				vcContext,
				msg.m_response.getWriter());
		} catch (Throwable e) {
			s_logger.error(e);
			e.printStackTrace();
		}

	}

	protected IAnswer performQuery(FlairMessage msg, VelocityContext vcContext) throws QueryException {
		Query query = msg.m_query;
		HttpSession session = msg.m_request.getSession();
		String sessionId = session.getId();
		IQueryModel queryModel = (IQueryModel)
			msg.getProfile(sessionId).getStructuredModel(IQueryModel.class);

		IAnswer answer = queryModel.query(query, false);

		return answer;
	}

	protected void fillContextWithAnswer(FlairMessage msg, VelocityContext vcContext, IAnswer answer) throws QueryException {
		vcContext.put("answer", answer);

		int pageIndex = 0;
		String page = msg.m_query.getFirstParamValue("page");
		if (page != null) {
			try {
				pageIndex = Integer.parseInt(page);
				pageIndex = Math.max(0, Math.min(pageIndex, answer.getPages().size() - 1));
			} catch (NumberFormatException e) {
				s_logger.warn("Bad page number " + page, e);
			}
		}
		vcContext.put("pageIndex", new Integer(pageIndex));

		vcContext.put("commonProperties", getCommonProperties(answer.getObjects(), msg));
	}

	protected SortedSet getCommonProperties(Set objects, FlairMessage msg) {
		//Profile profile = msg.getProfile();
		HttpSession session = msg.m_request.getSession();
		String sessionId = session.getId();	
		Profile profile = LongwellServer.getServer().getProfile(sessionId);
		Iterator iter = profile.getModel().listSubjects();
		
		Model model = profile.getModel();
		
		SortedSet properties = new TreeSet(new Comparator() {
			String m_locale;

			public boolean equals(Object obj) {
				return false;
			}

			public int compare(Object o1, Object o2) {
				IStructuredProperty p1 = (IStructuredProperty) o1;
				IStructuredProperty p2 = (IStructuredProperty) o2;

				int i = p1.getLabel(m_locale).compareToIgnoreCase(p2.getLabel(m_locale));
				if (i == 0) {
					i = p1.getURI().compareTo(p2.getURI());
				}
				return i;
			}

			public Comparator init(String locale) {
				m_locale = locale;
				return this;
			}
		}.init(msg.m_locale));
		if(objects!=null && objects.size()>0){
			properties.addAll(
					profile.getSchemaModel().getSortedStructuredProperties(objects));
		}
		// Default generic properties
		{
			properties.add(
				profile.getSchemaModel().getStructuredProperty(
					profile.getModel().createProperty(ITagModel.s_simile_tag)));
		}
		return properties;
	}
	protected Set getSchemas(FlairMessage msg) {
		SortedSet sSchemas = new TreeSet(new Comparator() {
			public boolean equals(Object obj) {
				return false;
			}

			public int compare(Object o1, Object o2) {
				IStructuredSchema ss1 = (IStructuredSchema) o1;
				IStructuredSchema ss2 = (IStructuredSchema) o2;

				return ss1.getURI().compareTo(ss2.getURI());
			}
		});

		sSchemas.addAll(msg.getProfileFromSession().getSchemaModel().getStructuredSchemas());
		return sSchemas;
	}	
}
